package com.zyf.project.binaryproto.annotation;

import com.zyf.project.binaryproto.codec.NumberEncoding;
import com.zyf.project.binaryproto.type.PrimitiveType;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * <h1>数据契约</h1>
 * <p>标记一个接口的字段作为数据契约的字段，作用于方法之上</p>
 *
 * @author Zhou Yifan
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DataField {

    /**
     * <p>字段顺序，顺序仅用于升序排序</p>
     * <p>对于已经发布使用的数据契约，都不应该调整顺序，否则会导致无法正确解析已有的数据</p>
     *
     * @return 字段顺序
     */
    int order();

    /**
     * <p>基本数据类型</p>
     * <p>如果字段类型属于 {@link PrimitiveType} 枚举类中的基本数据类型，则需要显示指定一种具体的类型</p>
     *
     * @return 基本数据类型
     */
    PrimitiveType primitiveType() default PrimitiveType.NIL;

    /**
     * <p>是否是枚举类型</p>
     * <p>如果为枚举类型（true），则属性的声明类型必须是枚举类型，且该枚举类型已经标记 {@link EnumContract}</p>
     *
     * @return 布尔值
     */
    boolean refEnum() default false;

    /**
     * 数值编码，只有 {@link #primitiveType()} 为整数 INT8~INT64 时有效
     *
     * @return 数值编码
     */
    NumberEncoding numberEncoding() default NumberEncoding.NONE;

    /**
     * 嵌套的数据契约类型，如果为 true，那么属性的声明必须是接口类型，且该类型已经被标记了 {@link DataContract}
     *
     * @return 布尔值
     */
    boolean refContract() default false;

    /**
     * 嵌套的契约类型是否根据实际的对象实现的契约接口动态写入
     *
     * @return 布尔值
     */
    boolean genericContract() default false;

    /**
     * 是否为列表
     *
     * @return 布尔值
     */
    boolean list() default false;

    /**
     * <p>最大长度，单位为 byte（字节）</p>
     * <p>进对于文本、字节数组、大整数等相关的数据类型有效</p>
     * <p>即 {@link PrimitiveType} 枚举类型中编码大于等于 0x20 {@link PrimitiveType#TEXT} 的数据类型</p>
     *
     * @return 最大长度，int 值
     */
    int maxSize() default -1;

    /**
     * 名称，默认为属性的名称
     *
     * @return 字符串值
     */
    String name() default "";

    /**
     * 关于字段的说明，说明内容将输出到数据段的数据结构描述文件中
     *
     * @return 字符串值
     */
    String description() default "";
}
